/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	main.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	20190509
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/
//两种下载方法 ETH_DOWNLOAD 或 COM_DOWNLOAD


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "includes.h"
#include "sys_tick.h"
#include "system_file.h"

/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/

#define BOOTLOADER_FLASH_SIZE	0x40000

#define IAP_ADDR	APP_FLASH_ADDR_START

#define SPI_READ_DATA_SIZE	W25X_SECTOR_SIZE
/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/

 
/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/
static uint8_t iap_app_index(void);
static void Stm32_Clock_Init(uint32_t plln,uint32_t pllm,uint32_t pllp,uint32_t pllq);
static void IapProgramRun(void);
static void Load_app(uint8_t iap_index);
/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/
extern log_console_t m_log_console;
/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/
static uint8_t spi_read_buff[SPI_READ_DATA_SIZE];

/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*                                                main()
*
* Description : This is the standard entry point for C code.  It is assumed that your code will call
*               main() once you have performed all necessary initialization.
*
* Arguments   : none
*
* Returns     : none
*********************************************************************************************************
*/

int main(void)
{
	// char iap_file_name[32];
	FIL iap_file;
	uint8_t reset_cmd = 0;
	Stm32_Clock_Init(160,5,2,4);
	SysTick->CTRL = SysTick->CTRL & (~SysTick_CTRL_ENABLE_Msk);
	system_cfg_init();
	char * iap_file_name = iap_file_read();
	iap_file_clear();
	if(iap_file_name == NULL)
	{
		Trace_Log("Read iap command form fs failed!\r\n");
	}
	else{
		Trace_Log("Read iap file name \"%s\" form fs;\r\n",iap_file_name);
	}
	bsp_uart_reveive_byte(m_log_console.p_uart,&reset_cmd,1000);
	
	if(reset_cmd == 'r' || reset_cmd == 'R')/*当启动boot的时候收到字符R时，即表示返回出厂设置*/
	{
		iap_file_name = IAP_BACKUP_FILE_NAME;
		Trace_Log("Get reset command form console, use iap file  \"%s\";\r\n",iap_file_name);
	}
	if(iap_file_name == NULL)
	{
		Trace_Log("None iap command,go to app!\r\\n");
	}
	else if( FR_OK == f_open(&iap_file,iap_file_name,FA_READ) )
	{
		iap_from_file(&iap_file);
		f_close(&iap_file);
	}
	else{
		Error_Log("Open iap file \"%s\" failed!\r\n",iap_file_name);
	}
	Trace_Log("Iap procedure complete,go to app!\r\\n");
	SysTick->CTRL = SysTick->CTRL & (~SysTick_CTRL_ENABLE_Msk);
	log_console_wait_cplt();
	bsp_timer_deinit();
	IapProgramRun();
}

static void IapProgramRun(void)
{
	uint32_t  IapSpInitVal;
	uint32_t  IapJumpAddr;
	void	(*pIapFun)(void);
	
	/*  */
	IapSpInitVal = (*((volatile uint32_t*)IAP_ADDR));
	if(( ((*((volatile uint32_t*)IAP_ADDR)))&0x2FF00000) == 0x24000000)
	{
		IapJumpAddr = *(uint32_t*)(IAP_ADDR + 4);
	
//		MSR_MSP(IapSpInitVal);
		pIapFun = (void(*)(void))IapJumpAddr;
		__set_MSP(*(__IO uint32_t*) IapSpInitVal);
		(*pIapFun)();
	}
}
static void Stm32_Clock_Init(uint32_t plln,uint32_t pllm,uint32_t pllp,uint32_t pllq)
{
	HAL_StatusTypeDef ret=HAL_OK;
	RCC_ClkInitTypeDef RCC_ClkInitStruct;
	RCC_OscInitTypeDef RCC_OscInitStruct;
  
	MODIFY_REG(PWR->CR3,PWR_CR3_SCUEN, 0);
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	while ((PWR->D3CR & (PWR_D3CR_VOSRDY)) != PWR_D3CR_VOSRDY) {}
  
	RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSEState=RCC_HSE_ON;
	RCC_OscInitStruct.HSIState=RCC_HSI_OFF;
	RCC_OscInitStruct.CSIState=RCC_CSI_OFF;
	RCC_OscInitStruct.PLL.PLLState=RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource=RCC_PLLSOURCE_HSE;

	RCC_OscInitStruct.PLL.PLLN=plln;
	RCC_OscInitStruct.PLL.PLLM=pllm;
	RCC_OscInitStruct.PLL.PLLP=pllp;
	RCC_OscInitStruct.PLL.PLLQ=pllq;

	RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
	RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
	ret=HAL_RCC_OscConfig(&RCC_OscInitStruct);
	if(ret!=HAL_OK) while(1);
  
	RCC_ClkInitStruct.ClockType=(RCC_CLOCKTYPE_SYSCLK|\
                                RCC_CLOCKTYPE_HCLK |\
                                RCC_CLOCKTYPE_D1PCLK1 |\
                                RCC_CLOCKTYPE_PCLK1 |\
                                RCC_CLOCKTYPE_PCLK2 |\
                                RCC_CLOCKTYPE_D3PCLK1);

	RCC_ClkInitStruct.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.SYSCLKDivider=RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.AHBCLKDivider=RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB1CLKDivider=RCC_APB1_DIV2; 
	RCC_ClkInitStruct.APB2CLKDivider=RCC_APB2_DIV2; 
	RCC_ClkInitStruct.APB3CLKDivider=RCC_APB3_DIV2;  
	RCC_ClkInitStruct.APB4CLKDivider=RCC_APB4_DIV4; 
	ret=HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
	if(ret!=HAL_OK) while(1);

	__HAL_RCC_CSI_ENABLE() ;
	__HAL_RCC_SYSCFG_CLK_ENABLE() ;  
	HAL_EnableCompensationCell();
}
